#include <iostream>

using namespace std;

template <class T1, class T2>
class foo;

template <class T1, class T2>
foo<T1,T2> operator+(const class foo<T1,T2> &, const class foo<T1,T2> &);

template <class T1, class T2>
class foo {
public:
        T1 a;
        T1 b;
        T2 d;
        foo() {}
        //foo(T1 aa, T1 bb, T2 dd) {a = aa, b = bb, d = dd;}
        foo(T1 aa, T1 bb, T2 dd);

        foo &operator=(const class foo &);

        friend foo operator+<T1,T2>(const class foo &, const class foo &);

        template <class T3, class T4>
        friend ostream &operator<<(ostream &os, const foo<T3, T4> &);
};

template <class T1, class T2>
foo<T1, T2>::foo(T1 aa, T1 bb, T2 dd)
{
        a = aa, b = bb, d = dd;
}

template <class T1, class T2>
foo<T1, T2> & foo<T1, T2>::operator=(const class foo &d)
{
        a = d.a; 
        b = d.b;
        this->d = d.d;
        return *this;
}

template <class T1, class T2>
foo<T1,T2> operator+(const class foo<T1,T2> &d1, const class foo<T1,T2> &d2)
{
        foo<T1,T2> tmp;
        tmp.a = d1.a + d2.a;
        tmp.b = d1.b + d2.b;
        tmp.d = d1.d + d2.d;
        return tmp;
}

template <class T1, class T2>
ostream &operator<<(ostream &os, const foo<T1, T2> &d)
{
        os << "(" << d.a << "," << d.b << "," << d.d << ")";
        return os;
}

int main()
{
        foo<int, double> bar(1, 3, 7.9);
        foo<int, double> xxx, yyy;

        cout << bar << endl;

        xxx = bar;
        cout << xxx << endl;

        yyy = xxx + bar;
        cout << yyy << endl;

        return 0;
}
